package com.cc.od.guess;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

/*
@description:
                            题目描述
                            设定一组四码的数字作为谜底，猜谜者进行猜测。
                            每猜一个数，出题者给出提示，提示以XAYB形式呈现：
                            X表示位置正确的数的个数（数字正确且位置正确）。
                            Y表示数字正确而位置不对的数的个数。
                            已知N组猜谜者猜的数字与对应的提示，如果答案确定，则输出答案；如果答案不确定，则输出“NA”。
                            输入格式
                            第一行输入一个正整数N（0<N<100），表示猜测的次数。
                            接下来N行，每一行包含一个猜测的数字（四位数）和一个提示结果（XAYB格式）。
                            输出格式
                            如果根据输入可以确定谜底数字，则输出这个四位数谜底。
                            如果无法确定谜底数字，则输出“NA”。
                            实现思路
                            解析输入：读取N以及接下来的N组猜测与提示。
                            构建候选集：
                            初始时，候选集为所有可能的四位数（0000-9999，但通常不考虑前导零，即1000-9999）。
                            根据每组猜测与提示，逐步缩小候选集。
                            更新候选集：
                            对于每组猜测与提示（如“1234 1A1B”），遍历候选集：
                            计算当前猜测与每个候选答案的X和Y值。
                            如果计算出的XAYB与提示不匹配，则从候选集中移除该候选答案。
                            确定答案：
                            如果候选集中只剩下一个答案，则输出该答案。
                            如果候选集为空或包含多个答案，则输出“NA”。
                            注意事项
                            在实现时，需要注意边界条件和特殊情况的处理，如输入的数字可能包含前导零，但实际谜底不会。
                            性能优化方面，可以考虑使用更高效的数据结构来存储和遍历候选集，以减少不必要得计算。
                            由于题目要求输出确定的谜底或“NA”，因此不需要输出猜测过程或中间结果。

                            猜数字解析：
                            根据这些输入，程序将输出谜底“3585”（如果这是唯一确定的答案）。如果答案不确定，则输出“NA”。
                            在“猜数字”的题目中，“1234 1A1B”这样的提示是一种特殊的反馈机制，用于告诉猜谜者他们的猜测与正确答案之间的关系。具体来说，“1234”是猜谜者给出的一个四位数猜测，而“1A1B”则是出题者根据这个猜测给出的反馈。

                            “A”前面的数字（在这个例子中是“1”）表示位置正确的数字的个数。也就是说，在猜谜者的猜测“1234”中，有1个数字不仅数字本身正确，而且它所在的位置也与正确答案中的位置相匹配。

                            “B”前面的数字（在这个例子中是“1”）表示数字正确但位置不正确的数字的个数。这意味着，在猜谜者的猜测“1234”中，还有另外1个数字虽然与正确答案中的某个数字相同，但它的位置并不正确。

                            然而，这个反馈并不直接告诉猜谜者哪些数字是正确的，也不告诉它们应该放在哪个位置。猜谜者需要根据这个反馈和自己的逻辑推理来逐渐缩小可能的答案范围。

                            例如，如果正确答案是“3585”，那么对于猜测“1234”：

                            “1A”表示有一个数字在正确的位置上。在这个例子中，没有数字既在猜测中又在答案中且位置相同，所以这部分反馈实际上是在告诉猜谜者他们的猜测中没有数字的位置是正确的（但这里可能是一个简化的表示，因为通常我们会期望至少有一个“A”或没有“A”但有多个“B”来给出有用的信息）。但在某些情况下，我们可以假设这是一个打字错误或特殊情况，并继续分析。

                            “1B”表示有一个数字在答案中，但在猜测中的位置不正确。在这个例子中，数字“3”和“5”都在答案中，但都不在猜测“1234”的正确位置上。不过，由于我们只知道有一个“B”，所以我们不能确定是哪一个数字。

                            实际上，对于这个问题，如果“1A1B”的“A”部分确实表示有一个数字位置正确（尽管在这个特定猜测中看起来不是这样），那么它可能是一个误导或特殊案例。在正常的游戏逻辑中，如果猜谜者得到的反馈是“0A2B”，那么他们会知道“1234”中有两个数字与答案中的数字相同，但位置都不对。这将帮助他们排除一些不可能的答案，并继续他们的猜测过程。

@ClassName GuessNumberGame
@author chen
@create 2024-09-29 17:41
@Version 1.0
*/
public class GuessNumberGame {

    public static void main(String[] args) {
        // 创建扫描器对象以读取输入
        Scanner scanner = new Scanner(System.in);

        // 读取猜测次数 N
        int N = scanner.nextInt();
        scanner.nextLine(); // 读取换行符
        Set<String> candidates = new HashSet<>();
        for (int i = 1000; i <= 9999; i++) {
            candidates.add(String.format("%04d", i));
        }
        for (int i = 0; i < N; i++) {
            String guess = scanner.next();
            String feedback = scanner.next();
            int XA = Character.getNumericValue(feedback.charAt(0));
            int YB = Character.getNumericValue(feedback.charAt(2));

            Set<String> newCandidates = new HashSet<>();
            for (String candidate : candidates) {
                if (evaluate(guess, candidate) == XA + YB * 10) {
                    newCandidates.add(candidate);
                }
            }
            candidates = newCandidates;
        }
        // 确定答案
        if (candidates.size() == 1) {
            System.out.println(candidates.iterator().next());
        } else {
            System.out.println("NA");
        }
    }


    private static int evaluate(String guess, String candidate) {
        // 初始化 X 和 Y 值
        int X = 0, Y = 0;
        // 用于标记数字是否已被使用
        boolean[] used = new boolean[4];

        // 计算 X（数字和位置都正确的数量）
        for (int i = 0; i < 4; i++) {
            if (guess.charAt(i) == candidate.charAt(i)) {
                X ++;
                used[i] = true;
            }
        }

        // 计算 Y（数字正确但位置不正确的数量）
        for (int i = 0; i < 4; i++) {
            if (!used[i]) {
                for (int j = 0; j < 4; j++) {
                    if (!used[j] && guess.charAt(i) == candidate.charAt(j)) {
                        Y++;
                        used[j] = true;
                        break;
                    }
                }
            }
        }

        // 返回计算结果，X 代表数字和位置都正确的数量，Y 代表数字正确但位置不正确的数量
        return X + Y * 10;
    }
}
